package com.link.base.base.orgnization.service;

import com.link.base.base.orgnization.dao.mybatis.mapper.LinkTableMapper;
import com.link.base.base.orgnization.dao.mybatis.mapper.OrgnizationMapper;
import com.link.base.base.orgnization.model.LinkTable;
import com.link.base.base.orgnization.model.Orgnization;
import com.link.base.base.position.dao.mybatis.mapper.PositionMapper;
import com.link.base.base.position.model.Position;
import com.link.base.base.system.model.TreeNode;
import com.link.base.base.system.utils.TreeUtil;
import com.link.base.basic.dao.mybatis.mapper.BasicCommonMapper;
import com.link.base.basic.model.ListOfValue;
import com.link.base.core.basic.util.YmlConstants;
import com.link.base.ext.emp.model.ExtEmployee;
import com.link.base.user.model.CoreUser;
import com.link.core.basic.dao.mapper.BasicMapper;
import com.link.core.basic.model.BasicModel;
import com.link.core.basic.model.CallParam;
import com.link.core.basic.query.Filter;
import com.link.core.basic.query.QueryParams;
import com.link.core.basic.query.Sorter;
import com.link.core.basic.service.BasicServiceException;
import com.link.core.basic.service.BasicServiceImpl;
import com.link.core.basic.service.ServiceException;
import com.link.core.cllog.LCLogger;
import com.link.core.util.StringUtils;
import com.link.core.util.UserUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author history update 18.11.06
 */
@Service
public class OrgnizationServiceImpl extends BasicServiceImpl<Orgnization> implements OrgnizationService {

    @Resource
    private OrgnizationMapper orgnizationMapper;

    @Resource
    private BasicCommonMapper basicCommonMapper;

    @Resource
    private PositionMapper positionMapper;

    @Resource
    private LinkTableMapper linkTableMapper;

    @Override
    public BasicMapper<Orgnization> getBasicMapper() {
        return orgnizationMapper;
    }

    @Override
    public List<Orgnization> queryListRemoveIdAndChildrenPage(Orgnization entity) throws Exception {
        String dataBase = "mysql";
        if (StringUtils.equals(YmlConstants.getApplicationDatabase(), dataBase)) {
            String str = orgnizationMapper.getOrgChildStr(entity);
            entity.setAttr6(str);
        }
        return orgnizationMapper.queryListRemoveIdAndChildrenPage(entity);
    }

    @Override
    public Orgnization queryRoot(Orgnization entity) throws Exception {
        return orgnizationMapper.queryRoot(entity);
    }

    @Override
    public void queryTreeByRoot(Orgnization entity) throws Exception {
        // treeOrgnizationList(entity);
        treeOrgList(entity);
    }

    /**
     * 递归查询组织树结构
     *
     * @throws BasicServiceException
     */
    private void treeOrgnizationList(Orgnization entity) throws Exception {
        QueryParams params = new QueryParams();
        params.addFilter(new Filter("parentOrgId", String.valueOf(entity.getId())));
        params.setPageFlag(false);
        Orgnization t = (Orgnization) BasicModel.transformClass(Orgnization.class, params);
        List<Orgnization> tempList = orgnizationMapper.queryByExamplePage(t);
        for (Orgnization temp : tempList) {
            treeOrgnizationList(temp);
        }
        entity.setChildren(tempList);
    }

    @Override
    public void queryTreeByRoot1(Orgnization entity) throws Exception {
        treeOrgnizationList1(entity);
    }

    private void treeOrgList(Orgnization entity) throws Exception {
        Orgnization t = new Orgnization();
        t.setPageFlag(false);
        QueryParams qps = new QueryParams();
        List<Sorter> sorters = new ArrayList<>();
        Sorter sorter = new Sorter();
        sorter.setProperty("orgCode");
        sorter.setDirection("ASC");
        sorters.add(sorter);
        qps.setSorters(sorters);
        t.setQps(qps);
        List<Orgnization> tempList = orgnizationMapper.queryByExamplePage(t);
        printOrgnizationList(tempList,entity);
    }

    private void printOrgnizationList(List<Orgnization> tempList, Orgnization entity) throws BasicServiceException {
        if (entity.getId() == null) {
            throw new ServiceException("ORGNIZATION-001");
        }
        List<Orgnization> childList = new ArrayList<>();
        for (Orgnization temp : tempList) {
            if (entity.getId().equals(temp.getParentOrgId())) {
                childList.add(temp);
            }
        }
        entity.setChildren(childList);
        for ( Orgnization org : childList) {
            printOrgnizationList(tempList,org);
        }
    }

    /**
     * 递归查询组织树结构
     *
     * @throws BasicServiceException
     */
    private void treeOrgnizationList1(Orgnization entity) throws Exception {
        ListOfValue record = new ListOfValue();
        record.setType("ORG_TYPE");
        record.setVal(entity.getOrgType());
        record = basicCommonMapper.getLovName(record);
        entity.setOrgType(record.getName());

        QueryParams params = new QueryParams();
        params.addFilter(new Filter("parentOrgId", String.valueOf(entity.getId())));
        params.setPageFlag(false);
        Orgnization t = (Orgnization) BasicModel.transformClass(Orgnization.class, params);
        List<Orgnization> tempList = orgnizationMapper.queryByExamplePage(t);
        for (Orgnization temp : tempList) {
            record.setVal(temp.getOrgType());
            record = basicCommonMapper.getLovName(record);
            temp.setOrgType(record.getName());
            treeOrgnizationList1(temp);
        }
        entity.setChildren(tempList);
    }

    @Override
    public void beforUpsert(Orgnization entity) throws Exception {
        super.beforUpsert(entity);
        if (StringUtils.isBlank(entity.getIsEffective())) {
            entity.setIsEffective("Y");
        }
    }

    @Override
    @Transactional(rollbackFor = BasicServiceException.class)
    public void insert(Orgnization entity) throws Exception {
        QueryParams params = new QueryParams();
        Orgnization t = (Orgnization) BasicModel.transformClass(Orgnization.class, params);
        //如果父组织没有指定，则添加默认父组织
        if (entity.getParentOrgId() == null) {
            //获取根组织的ID
            Long parentOrgId = orgnizationMapper.queryRoot(t).getId();
            entity.setParentOrgId(parentOrgId);
        }
        super.insert(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteWithChildById(Orgnization entity) throws Exception {
        beforDelete(entity);
        checkId(entity);
        QueryParams params = new QueryParams();
        params.setLoginCorpId(UserUtil.getUser().getLoginCorpId());
        params.setPageFlag(false);
        removeWithChilds(entity, params);
    }

    /**
     * 递归删除
     */
    private void removeWithChilds(Orgnization entity, QueryParams params) throws Exception {
        try {
            deleteById(entity);
            params.addFilter(new Filter("parentOrgId", String.valueOf(entity.getId())));
            Orgnization t = (Orgnization) BasicModel.transformClass(Orgnization.class, params);
            List<Orgnization> list = orgnizationMapper.queryByExamplePage(t);
            for (Orgnization orgnization : list) {
                this.removeWithChilds(orgnization, params);
            }
        } catch (Exception e) {
            LCLogger.withException(e);
            throw new RuntimeException(e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = BasicServiceException.class)
    public void getRunOrgUpdate(CallParam record) throws BasicServiceException {
        try {
            Long corpId = null;
            CoreUser user = UserUtil.getUser();
            if (user != null && null != user.getCorpid()) {
                corpId = user.getCorpid();
            }
            if (corpId == null) {
                throw new ServiceException("PUBLIC-044");
            }
            record.setParam1(corpId);
            /*存储过程版更新组织架构*/
            orgnizationMapper.getRunOrgSubUpdate(record);
            String ok = "OK";
            if (!StringUtils.equals(ok, record.getReturnStatus())) {
                throw new BasicServiceException(record.getMsgData());
            }
        } catch (Exception e) {
            LCLogger.withException(e);
            throw new BasicServiceException(e.getMessage());
        }
    }

    /**
     * 新版更新组织、部门、职位架构
     *
     * @author LiYang
     * @date 2019/12/12
     * @throws Exception
     */
    @Override
    public void runOrgUpdateNew(String type) throws Exception {
        CoreUser user = UserUtil.getUser();
        //基础表数据
        List<TreeNode> basicDataList = null;
        //查询参数，除了用于查询组织表外，在查询拉平表是也在使用
        Orgnization orgnization = new Orgnization();
        orgnization.setOrgType(type);
        orgnization.setCorpid(user.getCorpid());
        //当类型为组织时，给isOrg字段赋值为Y，查询组织
        if ("ORG".equals(type)) {
            orgnization.setIsOrg("Y");
            basicDataList = orgnizationMapper.queryAllOrgList(orgnization);
        }
        //查询部门
        if ("DEPT".equals(type)) {
            orgnization.setIsOrg("");
            basicDataList = orgnizationMapper.queryAllOrgList(orgnization);
        }
        //查询职位
        if ("POSTN".equals(type)) {
            Position postn = new Position();
            postn.setCorpid(user.getCorpid());
            postn.setPositionType("POSTN");
            basicDataList = positionMapper.queryAllPostnList(postn);
        }
        //如果没有基础数据直接返回
        if (null == basicDataList && basicDataList.size() <= 0) {
            return ;
        }
        //得到拉平表组织数据
        List<TreeNode> tilingList = orgnizationMapper.queryOrgRelList(orgnization);
        //将拉平表组织数据转为hash
        Map<String, TreeNode> tilingMap = new HashMap<>(131072);
        tilingMap = tilingList.stream()
                .collect(Collectors.toMap(TreeNode::getCombinationId, Function.identity(), (key1, key2) -> key2));
        //得到组织、部门、职位树
        List<TreeNode> tree = TreeUtil.buildTree(basicDataList);
        //将组织树进行自下而上的遍历，找出父子关系并将所需的增删改更新至拉平的hash
        TreeUtil.backwardSequenceTraversal(tree, tilingMap);
        //遍历拉平的hash，构建需要增删改的节点
        Map<String, List<TreeNode>> result = TreeUtil.generateOperateList(tilingMap);
        TreeUtil.updateDataToDb(result, type, user);
    }

    @Override
    public void getRunOrgUpdateNoCall(CallParam record) throws BasicServiceException {
        try {
            //获取所有组织
            Orgnization orgnization = new Orgnization();
            orgnization.setCorpid(record.getParam1());
            orgnization.setAttr1("O_");
            orgnization.setIsOrg("Y");
            orgnization.setOrgType("ORG");
            List<Orgnization> orgList = orgnizationMapper.queryCorpOrgList(orgnization);
            if (orgList != null && orgList.size() > 0) {
                //删除当前账套下在中间表的组织信息
                orgnizationMapper.deleteCorpInnerOrg(orgnization);
                //将组织信息插入中间拉平表
                setOrgPartyRelValues(orgList);
            }
            //获取所有部门
            orgnization.setIsOrg("");
            orgnization.setAttr1("D_");
            orgnization.setOrgType("DEPT");
            List<Orgnization> deptList = orgnizationMapper.queryCorpOrgList(orgnization);
            if (deptList != null && deptList.size() > 0) {
                orgnizationMapper.deleteCorpInnerOrg(orgnization);
                setOrgPartyRelValues(deptList);
            }
            Position position = new Position();
            position.setCorpid(record.getParam1());
            position.setPositionType("POSTN");
            List<Position> positionList = positionMapper.queryCorpPostnList(position);
            if (positionList != null && positionList.size() > 0) {
                //删除该账套下的组织职位拉平表里的职位数据
                positionMapper.deleteCorpInnerPostn(position);
                Integer num = 200 ;
                Integer count = positionList.size() / num;
                for (int i = 0; i < count + 1 ; i ++) {
                    if (i == count) {
                        positionMapper.insertPartyRelPostnList(positionList.subList(i * num,positionList.size()));
                    } else {
                        positionMapper.insertPartyRelPostnList(positionList.subList(i * num,(i + 1) * num));
                    }
                }

            }
            record.setReturnStatus("OK");
        } catch (Exception e) {
            record.setReturnStatus("ERROR");
            record.setMsgData(e.getMessage());
            LCLogger.withException(e);
            throw new ServiceException("ORGNIZATION-002");
        }
    }

    private void setOrgPartyRelValues(List<Orgnization> orgList) throws Exception {
        Integer num = 200 ;
        Integer count = orgList.size() / num;
        for (int i = 0; i < count + 1 ; i ++) {
            if (i == count) {
                orgnizationMapper.insertPartyRelList(orgList.subList(i * num,orgList.size()));
            } else {
                orgnizationMapper.insertPartyRelList(orgList.subList(i * num,(i + 1) * num));
            }
        }
    }

    @Override
    public List<Orgnization> queryCompanyInOrgnizationSelect(Orgnization entity) throws BasicServiceException {
        List<Orgnization> list = null;
        try {
            list = orgnizationMapper.queryCompanyInOrgnizationSelect(entity);
        } catch (Exception e) {
            LCLogger.withException(e);
            throw new BasicServiceException(e.getMessage());
        }
        return list;
    }

    @Override
    public void qdDeptIdUpdate(Long orgId, Long qdDeptId) throws Exception {
        if (orgId == null) {
            throw new ServiceException("PUBLIC-004");
        }
        Orgnization entity = new Orgnization();
        entity.setId(orgId);
        entity.setQdDeptId(qdDeptId);
        orgnizationMapper.qdDeptIdUpdate(entity);
    }

    /**
     * @author huanglongjian
     * @return List
     * @throws Exception
     * 查询联系人的组织
     */
    @Override
    public List<Orgnization> queryOrgByContactId(Orgnization entity) throws Exception {
        List<Orgnization> orgList = orgnizationMapper.queryOrgByContactId(entity);
        return orgList;
    }

    /**
     * @author huanglongjian
     * @return List
     * @throws Exception
     * 查询联系人的组织
     */
    @Override
    public List<Orgnization> queryOrgByAccountId(Orgnization entity) throws Exception {
        List<Orgnization> orgList = orgnizationMapper.queryOrgByAccountId(entity);
        return orgList;
    }

    /**
     * 获取所有表名
     */
    @Override
    public List<LinkTable> queryTableInfoList(LinkTable entity) throws Exception {
        String tableSchema = YmlConstants.getTableSchema();
        entity.setTableSchema(tableSchema);
        return orgnizationMapper.queryTableInfoList(entity);
    }

    @Override
    public List<LinkTable> queryColInfoListByTableName(LinkTable entity) throws Exception {
        String tableSchema = YmlConstants.getTableSchema();
        entity.setTableSchema(tableSchema);
        return orgnizationMapper.queryColInfoListByTableName(entity);
    }

    @Override
    public void saveCombineOrg(LinkTable entity) throws Exception {
        //判断非空条件数据
        if (entity.getOrgId() == null) {
            throw new ServiceException("合并后" + "PUBLIC-004");
        }
        if (StringUtils.isBlank(entity.getAttr1())) {
            throw new ServiceException("合并前" + "PUBLIC-004");
        }
        LinkTable linkTable = new LinkTable();
        //查询所有需更新的自定义字段
        List<LinkTable> resultList = linkTableMapper.queryAll(linkTable);
        linkTable.setColName("org_id");
        String tableSchema = YmlConstants.getTableSchema();
        linkTable.setTableSchema(tableSchema);
        //查询所有含有org_id的表
        List<LinkTable> defaultList = orgnizationMapper.queryColInfoListByTableName(linkTable);
        if (resultList != null && resultList.size() > 0) {
            for (LinkTable record : resultList) {
                record.setAttr1(entity.getAttr1());
                record.setOrgId(entity.getOrgId());
                orgnizationMapper.saveCombineOrg(record);
            }
        }
        if (defaultList != null && defaultList.size() > 0) {
            for (LinkTable linkTableOne : defaultList) {
                linkTableOne.setOrgId(entity.getOrgId());
                linkTableOne.setAttr1(entity.getAttr1());
                orgnizationMapper.saveCombineOrg(linkTableOne);
            }
        }
        linkTable.setAttr1(entity.getAttr1());
        linkTable.setAttr2("N");
        orgnizationMapper.orgStatusUpdate(linkTable);
    }

    @Override
    public Orgnization queryCompanyByOrgId(Orgnization entity) throws Exception {
        return orgnizationMapper.queryCompanyByOrgId(entity);
    }
    /**
     * 获取组织树，其中树包含根结点，且只含有有效的组织
     * @author 姚江漪
     * @date 2019/05/14 10:19
     */

    @Override
    public void queryTreeByRoot2(Orgnization entity) throws Exception {
        treeOrgnizationList2(entity);
    }

    /**
     * 获取组织树，其中树包含根结点，且只含有有效的组织
     * @author 姚江漪
     * @date 2019/05/14 10:19
     */
    private void treeOrgnizationList2(Orgnization entity) throws Exception {
        QueryParams params = new QueryParams();
        params.addFilter(new Filter("parentOrgId", String.valueOf(entity.getId())));
        params.addFilter(new Filter("isEffective", "Y"));
        params.setPageFlag(false);
        Orgnization t = (Orgnization) BasicModel.transformClass(Orgnization.class, params);
        List<Orgnization> tempList = orgnizationMapper.queryByExamplePage(t);
        for (Orgnization temp : tempList) {
            treeOrgnizationList2(temp);
        }
        entity.setChildren(tempList);
    }

    @Override
    public void beforInsert(Orgnization entity) throws Exception {
        if (Objects.isNull(entity)) {
            throw new BasicServiceException("Orgnization对象为空");
        }
        // 赋值默认父组织
        if (StringUtils.isBlank(entity.getParentOrgId().toString())) {
            Orgnization rootOrg = orgnizationMapper.queryRoot(entity);
            if (Objects.isNull(rootOrg)) {
                throw new BasicServiceException("无法查到默认的根组织");
            } else {
                entity.setParentOrgId(rootOrg.getId());
            }
        }
        super.beforInsert(entity);
    }

    /**
     * 通过组织id和组织类型，获取上级或下级组织信息
     * @author 秦学刚
     * @date 2019/04/30 01:16
     * @param orgnization
     */
    @Override
    public List<Orgnization> queryTierOrgnization(Orgnization orgnization) throws Exception {
        return orgnizationMapper.queryTierOrgnization(orgnization);
    }

    @Override
    public Orgnization queryUniqueShrOrgnization(Orgnization orgnization) {
        return orgnizationMapper.queryUniqueShrOrgnizationByOrgCode(orgnization);
    }

    @Override
    public Orgnization queryUniqueShrParOrgnization(Orgnization orgnization) {
        return orgnizationMapper.queryUniqueShrParOrgnization(orgnization);
    }

    @Override
    @Transactional
    public void updateForEsb(Orgnization orgnization) {
        orgnizationMapper.updateForEsb(orgnization);
    }

    @Override
    public Orgnization queryEmpOrgnizationByEmp(ExtEmployee employee) {
        return orgnizationMapper.queryEmpOrgnizationByEmp(employee);
    }

    @Override
    public void setDefaultParOrgnization(Orgnization orgnization) throws Exception {
        if (Objects.isNull(orgnization)) {
            throw new BasicServiceException("Orgnization对象为空");
        }
        Orgnization rootOrgnization = orgnizationMapper.queryRoot(new Orgnization());
        if (Objects.isNull(rootOrgnization)) {
            throw new BasicServiceException("无法找到默认的父组织");
        }
        orgnization.setParentOrgId(rootOrgnization.getId());
    }
}
